package com.gitee.feizns.reflect;

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.function.Function;

/**
 * @author feizns
 * @since 2019/5/15
 */
public abstract class ClassUtils {

    /**
     * 获取类型数组
     * @param params
     * @return
     */
    public static final Class<?>[] getClasses(Object... params) {
        return Arrays.stream(params).map(Object::getClass).toArray(Class[]::new);
    }

    /**
     * 获取一个类的继承体系，从子类开始到父类
     * @return
     */
    public static final Deque<Class<?>> getClasses(Class<?> type) {
        return getClasses(type, item -> item);
    }

    /**
     * 收集你所想拥有的。
     * 获取一个类的继承体系，从子类开始到父类
     * @return
     */
    public static final <T> Deque<T> getClasses(Class<?> type, Function<Class<?>, T> func) {
        Deque<T> deque = new LinkedList<>();
        while ( type != null ) {
            deque.offer(func.apply(type));
            type = type.getSuperclass();
        }
        return deque;
    }

    /**
     * 获取一个类的接口体系，向上延伸
     * @param type
     * @return
     */
    public static final Deque<Class<?>> getInterfaces(Class<?> type) {
        Deque<Class<?>> result = new LinkedList<>();

        Deque<Class<?>> interfaces = new LinkedList<>();
        interfaces.offer(type);
        while ( interfaces.isEmpty() == false ) {
            Class<?> remove = interfaces.remove();
            result.offer(remove);
            interfaces.addAll(Arrays.asList(remove.getInterfaces()));
        }

        return result;
    }

    /**
     * 获取一个类的继承体系和和接口体系 当前类 => 父类，当前类接口，父类接口
     * @param type
     * @return
     */
    public static final Queue<Class<?>> getClassesAndInterfaces(Class<?> type) {
        Deque<Class<?>> result = new LinkedList<>();
        result.addAll(getClasses(type));
        Arrays.stream(type.getInterfaces()).forEach(item -> result.addAll(getInterfaces(item)));
        return result;
    }

}
